home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume2 / libraris / gimme.5 < prev    next >
Text File  |  1988-12-02  |  47KB  |  1,838 lines

  1. Path: xanth!mcnc!gatech!bloom-beacon!mit-eddie!ll-xn!adelie!infinet!ulowell!page
  2. From: page@swan.ulowell.edu (Bob Page)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v02i078:  gimme.lib - misc library routines, Part05/07
  5. Message-ID: <10416@swan.ulowell.edu>
  6. Date: 2 Dec 88 01:02:33 GMT
  7. Organization: University of Lowell, Computer Science Dept.
  8. Lines: 1827
  9. Approved: page@swan.ulowell.edu
  10.  
  11. Submitted-by: oscvax!jan@uunet.UU.NET (Jan Sven Trabandt)
  12. Posting-number: Volume 2, Issue 78
  13. Archive-name: libraries/gimme.5
  14.  
  15. #    This is a shell archive.
  16. #    Remove everything above and including the cut line.
  17. #    Then run the rest of the file through sh.
  18. #----cut here-----cut here-----cut here-----cut here----#
  19. #!/bin/sh
  20. # shar:    Shell Archiver
  21. #    Run the following text with /bin/sh to create:
  22. #    globals.c
  23. #    graph.c
  24. #    inputhand.c
  25. #    intuistuff.c
  26. #    keyboard.c
  27. #    memchain.c
  28. #    menu.c
  29. #    menustuff.c
  30. #    message.c
  31. # This archive created: Thu Dec  1 19:52:10 1988
  32. cat << \SHAR_EOF > globals.c
  33. /*
  34.  *  FILE: globals.c
  35.  *  Some global declarations.
  36.  *  This allows inclusion of <gimmelib/gimmeall.h> without linking in entire
  37.  *  files containing global variables unnecessarily.
  38.  *
  39.  *  Public Domain, but keep my name in it as the original author.
  40.  *  31-Aug-88    Jan Sven Trabandt   first release version
  41.  */
  42.  
  43.  
  44. #define I_AM_GIM_GLOBALS
  45. #include "gimmelib/requester.h"
  46. #include "gimmelib/scrollbar.h"
  47.  
  48. /* generally usefull stuff */
  49. struct TextAttr gimMyFont = {
  50.     (STRPTR) "topaz.font",
  51.     TOPAZ_EIGHTY,
  52.     FS_NORMAL,
  53.     FPF_ROMFONT
  54.   };
  55.  
  56.  
  57. /* for requester.c */
  58. UBYTE *gimAutReqPostext = (UBYTE *) GAR_POSTEXT;
  59. UBYTE *gimAutReqNegtext = (UBYTE *) GAR_NEGTEXT;
  60.  
  61.  
  62. /* for scrollbar.c */
  63. USHORT gimDataOneScrollUp[] = {
  64.     0xffff,
  65.     0xffff,
  66.     0xfe7f,
  67.     0xfdbf,
  68.     0xfbdf,
  69.     0xf7ef,
  70.     0xeff7,
  71.     0xdffb,
  72.     0xffff
  73.   };
  74. USHORT gimDataOneScrollDown[] = {
  75.     0xffff, 0xdffb, 0xeff7, 0xf7ef, 0xfbdf,
  76.     0xfdbf, 0xfe7f, 0xffff, 0xffff
  77.   };
  78. USHORT gimDataOneScrollLeft[] = {
  79.     0xffff, 0xffcf, 0xff3f, 0xfcff, 0xf3ff,
  80.     0xfcff, 0xff3f, 0xffcf, 0xffff
  81.   };
  82. USHORT gimDataOneScrollRight[] = {
  83.     0xffff, 0xf3ff, 0xfcff, 0xff3f, 0xffcf,
  84.     0xff3f, 0xfcff, 0xf3ff, 0xffff
  85.   };
  86. SHAR_EOF
  87. cat << \SHAR_EOF > graph.c
  88. /*
  89.  *  FILE: graph.c
  90.  *  Support routines for creating and manipulating graphs.
  91.  *
  92.  *  Public Domain, but keep my name in it as the original author.
  93.  *  31-Oct-88    Jan Sven Trabandt   added to gimme.lib
  94.  */
  95.  
  96.  
  97. #define I_AM_GRAPH
  98. #include "gimmelib/gimmefuncs.h"
  99. #include "gimmelib/graph.h"
  100. #include "gimmelib/postext.h"
  101. #include <clib/macros.h>
  102.  
  103.  
  104. /* macros for internal scaling */
  105. #define SCALEUP(x)  ((long)(x) << SCALE)        /* x * 2^SCALE */
  106. #define SCALEDN(x)  ((long)(x) >> SCALE)        /* x / 2^SCALE */
  107.  
  108. /* macros to translate pixel offset from origin to pixel offset in rastport */
  109. #define TRANSX(gr,off)  ((short)((gr)->X.origin + (off)))
  110. #define TRANSY(gr,off)  ((short)((gr)->Y.origin - (off)))
  111.  
  112. /* leeways for titles */
  113. #define XLEEWAY     4
  114. #define YLEEWAY     3
  115.  
  116. #define TOLERANCE   2        /* pixel tolerance for fancy auto label */
  117.  
  118.  
  119. /* internal flags for graphWriteLabel */
  120. #define GWL_RESERVED_VAL    (0x0000ffffL)   /* lower short reserved for value */
  121. #define GWL_NO_HIGH        (1L << 16)      /* for internal use only!! */
  122.  
  123.  
  124. /* forward declarations */
  125. static SHORT coordToOffset();
  126. static SHORT offsetToCoord();
  127. static VOID  initAxis();
  128. static SHORT updateCoord();
  129. static VOID  doBlock();
  130.  
  131.  
  132. GRAPH *gimmeGraph( newgr, bm, areainfo, tmpras )
  133.     register NEWGRAPH    *newgr;
  134.     struct BitMap    *bm;
  135.     struct AreaInfo    *areainfo;
  136.     struct TmpRas    *tmpras;
  137. {
  138.     register GRAPH  *gr;
  139.     void        *mymh = NULL;
  140.     UBYTE        *raster;
  141.     SHORT        width, height;
  142.  
  143. #ifdef GIMME_WIMPY
  144.     if( !newgr ) {
  145.     return( NULL );
  146.     }
  147. #endif
  148.     if( !bm && (!newgr->rp || !newgr->rp->BitMap) ) {
  149.     return( NULL );
  150.     }
  151.     gr = (GRAPH *) chainAllocMem( &mymh, (ULONG)sizeof(GRAPH),
  152.                     MEMF_PUBLIC | MEMF_CLEAR );
  153.     if( !gr ) {
  154.     return( NULL );
  155.     }
  156.     if( !newgr->rp ) {
  157.     InitRastPort( &gr->rp );
  158.     } else {
  159.     gr->rp = *newgr->rp;        /* copy struct */
  160.     if( newgr->rp->Layer ) {
  161.         gr->rp.Layer = chainAllocMem( &mymh, (ULONG)sizeof(struct Layer),
  162.                         MEMF_PUBLIC | MEMF_CLEAR );
  163.         if( !gr->rp.Layer ) {
  164.         chainFreeMem( mymh );
  165.         return( NULL );
  166.         }
  167.         *gr->rp.Layer = *newgr->rp->Layer;    /* copy struct */
  168.         gr->rp.Layer->rp = &gr->rp;     /* make this layer come back */
  169.     }
  170.     }
  171.     if( bm ) {
  172.     gr->rp.BitMap = bm;
  173.     }
  174.  
  175.     gr->title  = newgr->title;
  176.     gr->xtitle = newgr->xtitle;
  177.     gr->ytitle = newgr->ytitle;
  178.     gr->FPen = newgr->FPen;
  179.     gr->BPen = newgr->BPen;
  180.     gr->AxesPen = newgr->AxesPen;
  181.     gr->XlabPen = gr->YlabPen = gr->AxesPen;
  182.     gr->TitlePen = newgr->TitlePen;
  183.     gr->XtitlePen = gr->YtitlePen = gr->TitlePen;
  184.     gr->flags = newgr->flags;
  185.     gr->ctlflags = newgr->ctlflags;
  186.     if( newgr->titleta ) {
  187.     gr->titletf = gimmeFont( newgr->titleta );
  188.     }
  189.     if( newgr->xta ) {
  190.     gr->xlabtf = gr->xtf = gimmeFont( newgr->xta );
  191.     }
  192.     if( newgr->yta ) {
  193.     gr->ylabtf = gr->ytf = gimmeFont( newgr->yta );
  194.     }
  195.  
  196.     if( !(gr->ctlflags & GGR_NOCLEARSTART) ) {
  197.     SetRast( &gr->rp, (long) gr->BPen );
  198.     }
  199.  
  200.     initAxis( gr, &gr->X, &newgr->X );
  201.     initAxis( gr, &gr->Y, &newgr->Y );
  202.     SetAPen( &gr->rp, (long) gr->FPen );
  203.     SetBPen( &gr->rp, (long) gr->BPen );
  204.     SetDrMd( &gr->rp, (ULONG) JAM1 );
  205.  
  206.     if( newgr->flags & (GGR_FILLTOX | GGR_FILLTOY) ) {
  207.     if( areainfo ) {
  208.         gr->rp.AreaInfo = areainfo;
  209.     } else if( !gr->rp.AreaInfo ) {
  210.         gr->rp.AreaInfo = chainAllocMem( &mymh,
  211.             (ULONG)sizeof(struct AreaInfo) + 5 * 2 * sizeof(LONG),
  212.             MEMF_PUBLIC | MEMF_CLEAR );
  213.         if( !gr->rp.AreaInfo ) {
  214.         chainFreeMem( mymh );
  215.         return( NULL );
  216.         }
  217.         InitArea( gr->rp.AreaInfo, (SHORT *)(gr->rp.AreaInfo + 1), 5L );
  218.     }
  219.     if( tmpras ) {
  220.         gr->rp.TmpRas = tmpras;
  221.     } else if( !gr->rp.TmpRas ) {
  222.         gr->rp.TmpRas = chainAllocMem( &mymh, (ULONG)sizeof(struct TmpRas),
  223.                         MEMF_PUBLIC | MEMF_CLEAR );
  224.         if( !gr->rp.TmpRas ) {
  225.         chainFreeMem( mymh );
  226.         return( NULL );
  227.         }
  228.         width = gr->rp.BitMap->BytesPerRow << 3;
  229.         height = gr->rp.BitMap->Rows;
  230.         raster = chainAllocMem( &mymh,
  231.             (long)RASSIZE((long)width, (long)height),
  232.                 MEMF_CHIP | MEMF_CLEAR );
  233.         if( !raster ) {
  234.         chainFreeMem( mymh );
  235.         return( NULL );
  236.         }
  237.         InitTmpRas( gr->rp.TmpRas, raster,
  238.                 (long)RASSIZE((long)width, (long)height) );
  239.     }
  240.     }
  241.  
  242.     if( !(gr->ctlflags & GGR_NOLABELS) ) {
  243.     drawGraphAxes( gr );
  244.     }
  245.  
  246.     if( gr->ctlflags & (GGR_INITPOINT | GGR_INITORIGIN) ) {
  247.     gr->points = 1;
  248.     } else {
  249.     gr->points = 0;
  250.     }
  251.     gr->memhead = mymh;
  252.     return( gr );
  253. } /* gimmeGraph */
  254.  
  255.  
  256. short getRidOfGraph( gr )
  257.     GRAPH   *gr;
  258. {
  259. #ifdef GIMME_WIMPY
  260.     if( !gr ) {
  261.     return( -1 );
  262.     }
  263. #endif
  264.     if( gr->ctlflags & GGR_CLEARONEND ) {
  265.     clearGraph( gr );
  266.     }
  267.     if( gr->ytf ) {
  268.     getRidOfFont( gr->ytf );
  269.     }
  270.     if( gr->xtf ) {
  271.     getRidOfFont( gr->xtf );
  272.     }
  273.     if( gr->titletf ) {
  274.     getRidOfFont( gr->titletf );
  275.     }
  276.     chainFreeMem( gr->memhead );
  277.     return( 0 );
  278. } /* getRidOfGraph */
  279.  
  280.  
  281. VOID clearGraph( gr )
  282.     register GRAPH  *gr;
  283. {
  284.     BYTE  fpen, bpen, axespen, titlepen;
  285.     BYTE  xlabpen, ylabpen, xtitlepen, ytitlepen;
  286.  
  287.     if( !(gr->ctlflags & GGR_NOCLEARSTART) ) {
  288.     SetRast( &gr->rp, (long) gr->BPen );
  289.     } else {
  290.     fpen = gr->FPen;
  291.     bpen = gr->BPen;
  292.     axespen = gr->AxesPen;
  293.     titlepen = gr->TitlePen;
  294.     xlabpen = gr->XlabPen;
  295.     ylabpen = gr->YlabPen;
  296.     xtitlepen = gr->XtitlePen;
  297.     ytitlepen = gr->YtitlePen;
  298.     gr->FPen = bpen;
  299.     gr->AxesPen = bpen;
  300.     gr->TitlePen = bpen;
  301.     gr->XlabPen = bpen;
  302.     gr->YlabPen = bpen;
  303.     gr->XtitlePen = bpen;
  304.     gr->YtitlePen = bpen;
  305.     SetAPen( &gr->rp, (long) bpen );
  306.  
  307.     RectFill( &gr->rp, (long) TRANSX(gr,1), (long) TRANSY(gr,gr->Y.size),
  308.             (long) TRANSX(gr,gr->X.size), (long) TRANSY(gr,1) );
  309.     if( !(gr->ctlflags & GGR_NOLABELS) ) {
  310.         drawGraphAxes( gr );
  311.     }
  312.  
  313.     gr->FPen = fpen;
  314.     gr->AxesPen = axespen;
  315.     gr->TitlePen = titlepen;
  316.     gr->XlabPen = xlabpen;
  317.     gr->YlabPen = ylabpen;
  318.     gr->XtitlePen = xtitlepen;
  319.     gr->YtitlePen = ytitlepen;
  320.     }
  321. } /* clearGraph */
  322.  
  323.  
  324. VOID resetGraph( gr )
  325.     register GRAPH  *gr;
  326. {
  327.     clearGraph( gr );
  328.  
  329.     gr->X.low  = gr->X.flow;
  330.     gr->X.high = gr->X.fhigh;
  331.     gr->X.lastdata = gr->X.fdata;
  332.     gr->X.lastoff  = gr->X.foff;
  333.  
  334.     gr->Y.low  = gr->Y.flow;
  335.     gr->Y.high = gr->Y.fhigh;
  336.     gr->Y.lastdata = gr->Y.fdata;
  337.     gr->Y.lastoff  = gr->Y.foff;
  338.  
  339.     if( gr->ctlflags & (GGR_INITPOINT | GGR_INITORIGIN) ) {
  340.     gr->points = 1;
  341.     } else {
  342.     gr->points = 0;
  343.     }
  344.  
  345.     if( !(gr->ctlflags & GGR_NOLABELS) ) {
  346.     drawGraphAxes( gr );
  347.     }
  348. } /* resetGraph */
  349.  
  350.  
  351. VOID drawGraphAxesOnly( gr )
  352.     register GRAPH  *gr;
  353. {
  354.     SHORT   maxrastlen, maxlen;
  355.  
  356.     SetAPen( &gr->rp, (long) gr->AxesPen );
  357.     Move( &gr->rp, (long) TRANSX(gr,0), (long) TRANSY(gr,gr->Y.size) );
  358.     Draw( &gr->rp, (long) TRANSX(gr,0), (long) TRANSY(gr,0) );
  359.     Draw( &gr->rp, (long) TRANSX(gr,gr->X.size), (long) TRANSY(gr,0) );
  360.     SetAPen( &gr->rp, (long) gr->FPen );
  361. } /* drawGraphAxesOnly */
  362.  
  363.  
  364. SHORT drawGraphAxes( gr )
  365.     register GRAPH  *gr;
  366. {
  367.     SHORT   maxrastlen, maxlen;
  368.     SHORT   yoff;
  369.     ULONG   flags;
  370.  
  371.     drawGraphAxesOnly( gr );
  372.     maxrastlen = graphWriteLabel( gr, GWL_XAXIS, gr->X.low, gr->X.high,
  373.                     gr->X.step );
  374.     maxlen = graphWriteLabel( gr, GWL_YAXIS, gr->Y.low, gr->Y.high,
  375.                 gr->Y.step );
  376.  
  377.     drawGraphTitle( gr, gr->X.size >> 1, gr->Y.size + YLEEWAY,
  378.             GPT_XCENTRE | GPT_YBOTTOM );
  379.  
  380.     yoff = - (YLEEWAY << 1);
  381.     if( !(gr->ctlflags & GGR_NOLABELS) ) {
  382.     yoff -= (gr->xlabtf ? gr->xlabtf->tf_YSize : gr->rp.TxHeight);
  383.     }
  384.     drawGraphXtitle( gr, gr->X.size >> 1, yoff, GPT_XCENTRE | GPT_YTOP );
  385.  
  386.     flags = GPT_XCENTRE | GPT_YBOTTOM | GPT_YUPWARDS;
  387.     if( (gr->ctlflags & GGR_HIRES) && !(gr->ctlflags & GGR_INTERLACE) ) {
  388.     flags |= GPT_XTHICKEN;
  389.     }
  390.     drawGraphYtitle( gr, -maxlen - XLEEWAY*2, gr->Y.size >> 1, flags );
  391.  
  392.     if( maxlen > maxrastlen ) {
  393.     maxrastlen = maxlen;
  394.     }
  395.     return( maxrastlen );
  396. } /* drawGraphAxes */
  397.  
  398.  
  399. VOID drawGraphTitle( gr, xoff, yoff, myflags )
  400.     register GRAPH  *gr;
  401.     SHORT        xoff, yoff;
  402.     ULONG        myflags;
  403. {
  404.     struct TextFont *tf;
  405.  
  406.     if( gr->title ) {
  407.     tf = gr->rp.Font;
  408.     if( gr->titletf ) {
  409.         SetFont( &gr->rp, gr->titletf );
  410.     }
  411.     SetAPen( &gr->rp, (long) gr->TitlePen );
  412.     positionText( &gr->rp, myflags, gr->title, 0L,
  413.             TRANSX(gr,xoff), TRANSY(gr,yoff) );
  414.     SetAPen( &gr->rp, (long) gr->FPen );
  415.     if( gr->titletf && tf ) {
  416.         SetFont( &gr->rp, tf );
  417.     }
  418.     }
  419. } /* drawGraphTitle */
  420.  
  421.  
  422. VOID drawGraphXtitle( gr, xoff, yoff, myflags )
  423.     register GRAPH  *gr;
  424.     SHORT        xoff, yoff;
  425.     ULONG        myflags;
  426. {
  427.     struct TextFont *tf;
  428.  
  429.     if( gr->xtitle ) {
  430.     tf = gr->rp.Font;
  431.     if( gr->xtf ) {
  432.         SetFont( &gr->rp, gr->xtf );
  433.     }
  434.     SetAPen( &gr->rp, (long) gr->XtitlePen );
  435.     positionText( &gr->rp, myflags, gr->xtitle, 0L,
  436.             TRANSX(gr,xoff), TRANSY(gr,yoff) );
  437.     SetAPen( &gr->rp, (long) gr->FPen );
  438.     if( gr->xtf && tf ) {
  439.         SetFont( &gr->rp, tf );
  440.     }
  441.     }
  442. } /* drawGraphXtitle */
  443.  
  444.  
  445. VOID drawGraphYtitle( gr, xoff, yoff, myflags )
  446.     register GRAPH  *gr;
  447.     SHORT        xoff, yoff;
  448.     ULONG        myflags;
  449. {
  450.     SHORT   destx, desty;
  451.     struct TextFont *tf;
  452.  
  453.     if( gr->ytitle ) {
  454.     tf = gr->rp.Font;
  455.     if( gr->ytf ) {
  456.         SetFont( &gr->rp, gr->ytf );
  457.     }
  458.     SetAPen( &gr->rp, (long) gr->YtitlePen );
  459.     positionText( &gr->rp, myflags, gr->ytitle, 0L,
  460.             TRANSX(gr,xoff), TRANSY(gr,yoff) );
  461.     SetAPen( &gr->rp, (long) gr->FPen );
  462.     if( gr->ytf && tf ) {
  463.         SetFont( &gr->rp, tf );
  464.     }
  465.     }
  466. } /* drawGraphYtitle */
  467.  
  468.  
  469. static SHORT coordToOffset( axis, coord )
  470.     register AXIS   *axis;
  471.     SHORT        coord;
  472. {
  473.     if( axis->scale <= 0 ) {
  474.     return( SCALEUP(coord - axis->low) / -axis->scale );
  475.     } else {
  476.     return( SCALEDN((coord - axis->low) * axis->scale) );
  477.     }
  478. } /* coordToOffset */
  479.  
  480.  
  481. static SHORT offsetToCoord( axis, offset )
  482.     register AXIS   *axis;
  483.     SHORT        offset;
  484. {
  485.     SHORT   coord;
  486.  
  487.     if( axis->scale <= 0 ) {
  488.     coord = SCALEDN(offset * -axis->scale);
  489.     } else {
  490.     /* offset in "window" belongs to next higher coordinate */
  491.     coord = (SCALEUP(offset) + axis->scale - 1) / axis->scale;
  492.     }
  493.     return( axis->low + coord );
  494. } /* offsetToCoord */
  495.  
  496.  
  497. /*  internal use only!!
  498.  *  initialize a graph's axis given a new axis structure
  499. static VOID initAxis( gr, axis, nax )
  500.     GRAPH        *gr;
  501.     register AXIS   *axis;
  502.     register NEWAXIS *nax;
  503. {
  504.     SHORT   temp;
  505.     SHORT   amt;
  506.     ULONG   flags;
  507.  
  508.     if( axis == &gr->X ) {
  509.     flags = gr->flags & GGR_X_FLAGS;
  510.     } else {
  511.     flags = gr->flags & GGR_Y_FLAGS;
  512.     }
  513.  
  514.     axis->origin = nax->origin;
  515.     axis->size = nax->size;
  516.     axis->flow = axis->low = nax->low;
  517.     axis->step = nax->step;
  518.     axis->labnum = nax->labnum;
  519.     if( !nax->labdenom ) {              /* to avoid divide by zero!! */
  520.     axis->labnum = 1;
  521.     axis->labdenom = 1;
  522.     } else {
  523.     axis->labdenom = nax->labdenom;
  524.     }
  525.     amt = nax->amt;
  526.     if( flags & (GGR_X_SPACING | GGR_Y_SPACING) ) {
  527.     if( !amt ) {
  528.         ++amt;
  529.     }
  530.     axis->scale = SCALEUP(amt);
  531.     temp = axis->size;
  532.     do {
  533.         axis->high = offsetToCoord( axis, temp );
  534.         axis->usesize = coordToOffset( axis, axis->high );
  535.     } while( axis->usesize > temp-- );
  536.     } else {
  537.     if( flags & (GGR_X_INTERVALS | GGR_Y_INTERVALS) ) {
  538.         if( amt <= 0 ) {
  539.         amt = 5;
  540.         }
  541.         axis->high = axis->low + amt;
  542.     } else { /* if( flags & (GGR_X_MAX | GGR_Y_MAX) ) */
  543.         if( amt < axis->low ) {
  544.         amt = axis->low + 5;
  545.         }
  546.         axis->high = amt;
  547.     }
  548.  
  549.     temp = axis->high - axis->low;
  550.     if( temp >= nax->size ) {
  551.         axis->scale = - ( SCALEUP(temp) / axis->size );
  552.         temp = SCALE - 1;
  553.         while( (axis->usesize = coordToOffset(axis, axis->high))
  554.             > axis->size ) {
  555.         if( temp < 0 ) break;
  556.         axis->scale -= SCALEUP(5) >> temp;
  557.         --temp;
  558.         } /* while */
  559.  
  560.         if( flags & (GGR_X_INTEGRAL | GGR_DELTAX |
  561.                 GGR_Y_INTEGRAL | GGR_DELTAY) ) {
  562.         if( (temp = SCALEUP(SCALEDN(-axis->scale))) < -axis->scale ) {
  563.             axis->scale = -SCALEUP( SCALEDN(-axis->scale) + 1 );
  564.         } else {
  565.             axis->scale = -temp;
  566.         }
  567.         }
  568.     } else {
  569.         axis->scale = SCALEUP(axis->size) / temp;
  570.         if( flags & (GGR_X_INTEGRAL | GGR_DELTAX |
  571.                 GGR_Y_INTEGRAL | GGR_DELTAY) ) {
  572.         axis->scale = SCALEUP( SCALEDN(axis->scale) );
  573.         }
  574.         axis->usesize = coordToOffset( axis, axis->high );
  575.     }
  576.     }
  577.  
  578.     axis->fhigh = axis->high;
  579.     if( gr->ctlflags & GGR_INITPOINT ) {
  580.     axis->lastdata = nax->initpt;
  581.     axis->lastoff = coordToOffset( axis, axis->lastdata );
  582.     } else {    /* if( gr->ctlflags & GGR_INITORIGIN ) */
  583.     axis->lastdata = axis->low;
  584.     axis->lastoff = 1;
  585.     }
  586.     axis->fdata = axis->lastdata;
  587.     axis->foff = axis->lastoff;
  588.     if( !axis->scale ) {
  589.     axis->scale = 1;        /* to avoid divide by zero!! */
  590.     }
  591. } /* initAxis */
  592.  
  593.  
  594. SHORT graphWriteLabel( gr, myflags, first, last, step )
  595.     register GRAPH  *gr;
  596.     ULONG        myflags;
  597.     SHORT        first, last;
  598.     SHORT        step;
  599. {
  600.     AXIS    *axis;
  601.     SHORT   full, spacing;
  602.     SHORT   low, high;
  603.     SHORT   maxrlen = 0, len;
  604.     SHORT   coord, loop;
  605.     SHORT   x, y;
  606.     struct TextFont *tf;
  607.     BYTE    xpen, ypen;
  608.     BYTE    bpen, dmode;
  609.  
  610.     if( !(myflags & GWL_NO_HIGH) ) {
  611.     if( myflags & (GWL_CLEAR_OLD | GWL_CLEAR_ONLY) ) {
  612.         if( myflags & GWL_XAXIS ) {
  613.         xpen = gr->XlabPen;
  614.         gr->XlabPen = gr->BPen;
  615.         } else {
  616.         ypen = gr->YlabPen;
  617.         gr->YlabPen = gr->BPen;
  618.         }
  619.         maxrlen = graphWriteLabel( gr,
  620.                 myflags & ~(GWL_CLEAR_OLD | GWL_CLEAR_ONLY),
  621.                 first, last, step );
  622.         if( myflags & GWL_XAXIS ) {
  623.         gr->XlabPen = xpen;
  624.         } else {
  625.         gr->YlabPen = ypen;
  626.         }
  627.         if( myflags & GWL_CLEAR_ONLY ) {
  628.         return( maxrlen );
  629.         }
  630.     }
  631.     tf = gr->rp.Font;
  632.     bpen = gr->rp.BgPen;
  633.     dmode = gr->rp.DrawMode;
  634.     if( myflags & GWL_XAXIS ) {
  635.         SetAPen( &gr->rp, (long) gr->XlabPen );
  636.         if( gr->xlabtf ) {
  637.         SetFont( &gr->rp, gr->xlabtf );
  638.         }
  639.     } else {            /* else YAXIS */
  640.         SetAPen( &gr->rp, (long) gr->YlabPen );
  641.         if( gr->ylabtf ) {
  642.         SetFont( &gr->rp, gr->ylabtf );
  643.         }
  644.     }
  645.     }
  646.  
  647.     if( step > 0 ) {                /* if we want even-spaced labels */
  648.     for( loop = first; loop <= last; loop += step ) {
  649.         if( myflags & GWL_YAXIS) {
  650.         y = coordToOffset(&gr->Y, loop);
  651.         WritePixel( &gr->rp, (long)TRANSX(gr,-1), (long)TRANSY(gr,y) );
  652.         len = positionText( &gr->rp, GPT_XRIGHT | GPT_YCENTREBASE, NULL,
  653.                 (long) (loop) * gr->Y.labnum / gr->Y.labdenom,
  654.                 TRANSX(gr,-XLEEWAY), TRANSY(gr,y) );
  655.         } else {    /* x-axis */
  656.         x = coordToOffset(&gr->X, loop);
  657.         WritePixel( &gr->rp, (long)TRANSX(gr,x), (long)TRANSY(gr,-1) );
  658.         len = positionText( &gr->rp, GPT_XCENTRE | GPT_YTOP, NULL,
  659.                 (long) (loop) * gr->X.labnum / gr->X.labdenom,
  660.                 TRANSX(gr,x), TRANSY(gr,-YLEEWAY) );
  661.         }
  662.         maxrlen = MAX(maxrlen, len);
  663.     } /* for */
  664.     } else {
  665.     if( myflags & GWL_YAXIS) {
  666.         high = coordToOffset(&gr->Y, last);
  667.         if( !(myflags & GWL_NO_HIGH) ) {
  668.         WritePixel( &gr->rp, (long)TRANSX(gr,-1),
  669.                 (long)TRANSY(gr,high) );
  670.         maxrlen = positionText(&gr->rp, GPT_XRIGHT | GPT_YCENTREBASE,
  671.                 NULL, (long) (last) * gr->Y.labnum / gr->Y.labdenom,
  672.                 TRANSX(gr,-XLEEWAY), TRANSY(gr,high) );
  673.         }
  674.         low = coordToOffset(&gr->Y, first);
  675.         WritePixel( &gr->rp, (long)TRANSX(gr,-1), (long)TRANSY(gr,low) );
  676.         positionText( &gr->rp, GPT_XRIGHT | GPT_YCENTREBASE, NULL,
  677.                 (long) (first) * gr->Y.labnum / gr->Y.labdenom,
  678.                 TRANSX(gr,-XLEEWAY), TRANSY(gr,low) );
  679.         full = gr->rp.TxHeight;
  680.         axis = &gr->Y;
  681.     } else {       /* x-axis */
  682.         high = coordToOffset(&gr->X, last);
  683.         if( !(myflags & GWL_NO_HIGH) ) {
  684.         WritePixel( &gr->rp, (long)TRANSX(gr,high),
  685.                 (long)TRANSY(gr,-1) );
  686.         maxrlen = positionText( &gr->rp, GPT_XCENTRE| GPT_YTOP, NULL,
  687.                 (long) (last) * gr->X.labnum / gr->X.labdenom,
  688.                 TRANSX(gr,high), TRANSY(gr,-YLEEWAY) );
  689.         full = maxrlen;
  690.         myflags = (myflags & ~0xFFFFL) | full;
  691.         } else {
  692.         full = myflags & 0xFFFFL;
  693.         }
  694.         low = coordToOffset(&gr->X, first);
  695.         WritePixel( &gr->rp, (long)TRANSX(gr,low), (long)TRANSY(gr,-1) );
  696.         positionText( &gr->rp, GPT_XCENTRE | GPT_YTOP, NULL,
  697.                 (long) (first) * gr->X.labnum / gr->X.labdenom,
  698.                 TRANSX(gr,low), TRANSY(gr,-YLEEWAY) );
  699.         axis = &gr->X;
  700.     }
  701.     spacing = full << 1;
  702.     low += spacing;
  703.     coord = offsetToCoord( axis, low );
  704.     low = coordToOffset( axis, coord );
  705.     if( high - low >= spacing - TOLERANCE ) {
  706.         graphWriteLabel( gr, myflags | GWL_NO_HIGH, coord, last, step );
  707.     }
  708.     }
  709.  
  710.     if( !(myflags & GWL_NO_HIGH) ) {
  711.     SetAPen( &gr->rp, (long) gr->FPen );
  712.     if( tf ) {
  713.         SetFont( &gr->rp, tf );
  714.     }
  715.     }
  716.     return( maxrlen );
  717. } /* graphWriteLabel */
  718.  
  719.  
  720. VOID addToGraph( gr, x, y )
  721.     register GRAPH  *gr;
  722.     SHORT        x, y;
  723. {
  724.     SHORT   amt;
  725.     SHORT   newX, newY;
  726.  
  727.     newX = updateCoord( gr, &gr->X, x );
  728.     newY = updateCoord( gr, &gr->Y, y );
  729.     SetAPen( &gr->rp, (long) gr->FPen );
  730.     if( !(gr->ctlflags & GGR_NOCONNECTLINE) ) {
  731.     Move( &gr->rp, (long) TRANSX(gr,gr->X.lastoff),
  732.                 (long) TRANSY(gr,gr->Y.lastoff) );
  733.     Draw( &gr->rp, (long)TRANSX(gr,newX), (long)TRANSY(gr,newY) );
  734.     } else {
  735.     Move( &gr->rp, (long)TRANSX(gr,newX), (long)TRANSY(gr,newY) );
  736.     }
  737.  
  738.     if( gr->flags & GGR_LINETOX ) {
  739.     Move( &gr->rp, (long)TRANSX(gr,newX), (long)TRANSY(gr,newY) );
  740.     Draw( &gr->rp, (long)TRANSX(gr,newX), (long)TRANSY(gr,1) );
  741.     }
  742.     if( gr->flags & GGR_LINETOY ) {
  743.     Move( &gr->rp, (long)TRANSX(gr,newX), (long)TRANSY(gr,newY) );
  744.     Draw( &gr->rp, (long)TRANSX(gr,1), (long)TRANSY(gr,newY) );
  745.     }
  746.  
  747.     if( gr->flags & GGR_FILLTOX ) {
  748.     doBlock( &gr->rp, TRANSX(gr, gr->X.lastoff), TRANSY(gr, 1),
  749.             TRANSX(gr, gr->X.lastoff), TRANSY(gr, gr->Y.lastoff),
  750.             TRANSX(gr, newX), TRANSY(gr, newY),
  751.             TRANSX(gr, newX), TRANSY(gr, 1) );
  752.     }
  753.     if( gr->flags & GGR_FILLTOY ) {
  754.     doBlock( &gr->rp, TRANSX(gr, 1), TRANSY(gr, gr->Y.lastoff),
  755.             TRANSX(gr,gr->X.lastoff), TRANSY(gr, gr->Y.lastoff),
  756.             TRANSX(gr, newX), TRANSY(gr, newY),
  757.             TRANSX(gr, 1), TRANSY(gr, newY) );
  758.     }
  759.  
  760.     if( gr->flags & GGR_BLACKTOX ) {
  761.     SetAPen( &gr->rp, (long) gr->BPen );
  762.     Move( &gr->rp, (long) TRANSX(gr, gr->X.lastoff),(long)TRANSY(gr, 1) );
  763.     Draw( &gr->rp, (long) TRANSX(gr, gr->X.lastoff),
  764.             (long) TRANSY(gr, gr->Y.lastoff) );
  765.     SetAPen( &gr->rp, (long) gr->FPen );
  766.     }
  767.     if( gr->flags & GGR_BLACKTOY ) {
  768.     SetAPen( &gr->rp, (long) gr->BPen );
  769.     Move(&gr->rp, (long) TRANSX(gr, 1),(long)TRANSY(gr, gr->Y.lastoff) );
  770.     Draw(&gr->rp, (long) TRANSX(gr, gr->X.lastoff),
  771.               (long) TRANSY(gr, gr->Y.lastoff) );
  772.     SetAPen( &gr->rp, (long) gr->FPen );
  773.     }
  774.  
  775.     gr->X.lastoff = newX;
  776.     gr->Y.lastoff = newY;
  777.     ++gr->points;
  778. } /* addToGraph */
  779.  
  780.  
  781. /*  internal use only!!
  782.  *  add a coordinate to an axis, doing the actual scrolling if necessary
  783.  *  and updating some AXIS fields
  784.  *
  785.  *  note: truncates to the rectangle defined by the origin and the axis' size.
  786.  *
  787.  *  returns the standard pixel offset for the coordinate
  788. static SHORT updateCoord( gr, axis, coord )
  789.     GRAPH        *gr;
  790.     register AXIS   *axis;
  791.     SHORT        coord;
  792. {
  793.     SHORT   offset;
  794.     SHORT   amt;
  795.     LONG    Xamt, Yamt;
  796.     ULONG   flags, awlflags;
  797.  
  798.     if( axis == &gr->X ) {
  799.     flags = gr->flags & GGR_X_FLAGS;
  800.     } else {
  801.     flags = gr->flags & GGR_Y_FLAGS;
  802.     }
  803.     if( flags & (GGR_DELTAX | GGR_DELTAY) ) {
  804.     axis->lastdata += coord;
  805.     offset = coordToOffset( axis, axis->lastdata );
  806.     if( offset > axis->usesize ) {
  807.         if( axis == &gr->X ) {
  808.         Xamt = amt = offset - axis->lastoff;
  809.         Yamt = 0L;
  810.         } else {
  811.         Xamt = 0L;
  812.         Yamt = amt = offset - axis->lastoff;
  813.         }
  814.         ScrollRaster( &gr->rp, (long) Xamt, (long) Yamt,
  815.         (long) TRANSX(gr,1), (long) TRANSY(gr,gr->Y.size),
  816.         (long) TRANSX(gr,axis->size), (long) TRANSY(gr,1) );
  817.         awlflags = (axis == &gr->X) ? GWL_XAXIS : GWL_YAXIS;
  818.         if( !(gr->ctlflags & GGR_NOLABELS) ) {
  819.         graphWriteLabel( gr, awlflags | GWL_CLEAR_ONLY, axis->low,
  820.                     axis->high, axis->step );
  821.         }
  822.         axis->low += coord;
  823.         axis->high += coord;
  824.         /* drawGraphAxesOnly( gr ); */
  825.         if( !(gr->ctlflags & GGR_NOLABELS) ) {
  826.         graphWriteLabel( gr, awlflags, axis->low, axis->high,
  827.                     axis->step );
  828.         }
  829.         offset = axis->lastoff;
  830.         axis->lastoff -= amt;
  831.     }
  832.     } else {
  833.     offset = coordToOffset( axis, coord );
  834.     if( offset < 0 ) {
  835.         offset = 0;
  836.     } else if( offset > axis->size ) {
  837.         offset = axis->size;
  838.     }
  839.     axis->lastdata = coord;
  840.     }
  841.  
  842.     return( offset );
  843. } /* updateCoord */
  844.  
  845.  
  846. /*  internal use only!!
  847.  *  do an area fill on the 4 pairs of coordinates,
  848.  *  clipped to the rastport's bitmap size
  849.  *  NOTE: the TmpRas should be (at least) the same size as this bitmap
  850. static VOID doBlock( rp, x1, y1, x2, y2, x3, y3, x4, y4 )
  851.     register struct RastPort    *rp;
  852.     SHORT            x1, y1, x2, y2, x3, y3, x4, y4;
  853. {
  854.     SHORT   width, height;
  855.  
  856.     width = rp->BitMap->BytesPerRow << 3;
  857.     height = rp->BitMap->Rows;
  858.  
  859.     if( x1 < 0 ) x1 = 0;
  860.     else if( x1 > width ) x1 = width;
  861.     if( x2 < 0 ) x2 = 0;
  862.     else if( x2 > width ) x2 = width;
  863.     if( x3 < 0 ) x3 = 0;
  864.     else if( x3 > width ) x3 = width;
  865.     if( x4 < 0 ) x4 = 0;
  866.     else if( x4 > width ) x4 = width;
  867.  
  868.     if( x1 == x3 ) return;
  869.  
  870.     if( y1 < 0 ) y1 = 0;
  871.     else if( y1 > height ) y1 = height;
  872.     if( y2 < 0 ) y2 = 0;
  873.     else if( y2 > height ) y2 = height;
  874.     if( y3 < 0 ) y3 = 0;
  875.     else if( y3 > height ) y3 = height;
  876.     if( y4 < 0 ) y4 = 0;
  877.     else if( y4 > height ) y4 = height;
  878.  
  879.     if( y1 == y3 ) return;
  880.  
  881.     AreaMove( rp, (long) x1, (long) y1 );
  882.     AreaDraw( rp, (long) x2, (long) y2 );
  883.     AreaDraw( rp, (long) x3, (long) y3 );
  884.     AreaDraw( rp, (long) x4, (long) y4 );
  885.     AreaEnd( rp );
  886. } /* doBlock */
  887. SHAR_EOF
  888. cat << \SHAR_EOF > inputhand.c
  889. /*
  890.  *  FILE: inputhand.c
  891.  *  Support routines for installing/removing an input handler.
  892.  *
  893.  *  Public Domain, but keep my name in it as the original author.
  894.  *  31-Oct-88    Jan Sven Trabandt   added to gimme.lib
  895.  */
  896.  
  897.  
  898. #define I_AM_INPUTHAND
  899. #include "gimmelib/gimmefuncs.h"
  900.  
  901.  
  902. struct IOStdReq *addInputHandler( handler, data, pri, name )
  903.     void    (*handler)();
  904.     APTR    data;
  905.     BYTE    pri;
  906.     UBYTE   *name;
  907. {
  908.     struct MsgPort    *port;
  909.     struct IOStdReq    *ioreq;
  910.     struct Interrupt    *handint;
  911.  
  912. #ifdef GIMME_WIMPY
  913.     if( !handler ) {
  914.     return( NULL );
  915.     }
  916. #endif
  917.     if( !(port = CreatePort(NULL, 0L)) ) {
  918.     return( NULL );
  919.     }
  920.     if( !(ioreq = CreateStdIO(port)) ) {
  921.     DeletePort( port );
  922.     return( NULL );
  923.     }
  924.     if( !(handint = AllocMem((ULONG)sizeof(struct Interrupt),
  925.                 MEMF_PUBLIC | MEMF_CLEAR)) ) {
  926.     DeleteStdIO( ioreq );
  927.     DeletePort( port );
  928.     return( NULL );
  929.     }
  930.     handint->is_Data = data;
  931.     handint->is_Code = handler;
  932.     handint->is_Node.ln_Type = NT_MESSAGE;
  933.     handint->is_Node.ln_Pri = pri;
  934.     handint->is_Node.ln_Name = (char *) name;
  935.     if( OpenDevice("input.device", 0L, ioreq, 0L) ) {
  936.     FreeMem( handint, (ULONG)sizeof(struct Interrupt) );
  937.     DeleteStdIO( ioreq );
  938.     DeletePort( port );
  939.     return( NULL );
  940.     }
  941.     ioreq->io_Command = IND_ADDHANDLER;
  942.     ioreq->io_Data = (APTR) handint;
  943.     ioreq->io_Length = sizeof(struct Interrupt);
  944.     if( DoIO(ioreq) ) {
  945.     CloseDevice( ioreq );
  946.     FreeMem( handint, (ULONG)sizeof(struct Interrupt) );
  947.     DeleteStdIO( ioreq );
  948.     DeletePort( port );
  949.     return( NULL );
  950.     }
  951.     return( ioreq );
  952. } /* addInputHandler */
  953.  
  954.  
  955. short removeInputHandler( ioreq )
  956.     struct IOStdReq *ioreq;
  957. {
  958. #ifdef GIMME_WIMPY
  959.     if( !ioreq ) {
  960.     return( -1 );
  961.     }
  962. #endif
  963.     ioreq->io_Command = IND_REMHANDLER;
  964.     ioreq->io_Message.mn_Node.ln_Type = NT_MESSAGE;
  965.     if( DoIO(ioreq) ) {
  966.     return( -1 );
  967.     }
  968.     CloseDevice( ioreq );
  969.     FreeMem( ioreq->io_Data, (ULONG)sizeof(struct Interrupt) );
  970.     DeletePort( ioreq->io_Message.mn_ReplyPort );
  971.     DeleteStdIO( ioreq );
  972.     return( 0 );
  973. } /* removeInputHandler */
  974. SHAR_EOF
  975. cat << \SHAR_EOF > intuistuff.c
  976. /*
  977.  *  FILE: intuistuff.c
  978.  *  Support routines for creating some useful intuition-type structures.
  979.  *
  980.  *  Public Domain, but keep my name in it as the original author.
  981.  *  31-Aug-88    Jan Sven Trabandt   first release version
  982.  *  31-Oct-88    Jan Sven Trabandt   made gimmeBorder more flexible/efficient
  983.  */
  984.  
  985.  
  986. #define I_AM_INTUISTUFF
  987. #include "gimmelib/gimmefuncs.h"
  988. #include "gimmelib/intuistuff.h"
  989. #include "gimmelib/macros.h"
  990.  
  991.  
  992. /* WSL-type construct */
  993. #define GUESS        do {
  994. #define QUIF( cond )    if( cond ) break;
  995. #define ENDGUESS    } while( 0 );
  996.  
  997.  
  998. struct Border *gimmeBorder( mh, xsize, ysize )
  999.     void    **mh;
  1000.     SHORT   xsize, ysize;
  1001. {
  1002.     register struct Border  *bp;
  1003.     register SHORT        *r;
  1004.     ULONG            size;
  1005.     void            *mymh = NULL;
  1006.     void            **mhdr = &mymh;
  1007.  
  1008.     GUESS
  1009.     size = sizeof(struct Border);
  1010.     if( !mh ) {
  1011.         r = AllocMem( (ULONG)sizeof(SHORT) * 2 * 5, MEMF_PUBLIC );
  1012.         QUIF( !r );
  1013.         mhdr = NULL;
  1014.     } else {
  1015.         if( xsize > 0 && ysize > 0 ) {
  1016.         /* need room for 5 pairs of shorts as well */
  1017.         size = sizeof(struct Border) + sizeof(SHORT) * 2 * 5;
  1018.         r = NULL;
  1019.         }
  1020.     }
  1021.     bp = chainAllocMem( mhdr, (ULONG) size, MEMF_CLEAR | MEMF_PUBLIC );
  1022.     QUIF( !bp );
  1023.     bp->FrontPen = 1;
  1024.     bp->DrawMode = JAM1;
  1025.     if( xsize > 0 && ysize > 0 ) {
  1026.         if( !r ) {
  1027.         r = (SHORT *) (bp + 1);
  1028.         }
  1029.         bp->XY = r;
  1030.         r[2] = r[4] = xsize - 1;
  1031.         r[5] = r[7] = ysize - 1;
  1032.         bp->Count = 5;
  1033.     }
  1034.     linkChainMem( mh, mymh );
  1035.     return( bp );
  1036.     ENDGUESS
  1037.     if( mhdr ) {
  1038.     chainFreeMem( mymh );
  1039.     } else {
  1040.     if( r ) {
  1041.         FreeMem( r, (ULONG) sizeof(SHORT) * 2 * 5 );
  1042.     }
  1043.     }
  1044.     return( NULL );
  1045. } /* gimmeBorder */
  1046.  
  1047.  
  1048. struct Image *gimmeImage( mh, depth, width, height )
  1049.     void    **mh;
  1050.     SHORT   depth, width, height;
  1051. {
  1052.     register struct Image   *ip;
  1053.     ULONG   size;            /* image datasize (bytes) for allocation */
  1054.     void    *mymh = NULL;
  1055.     void    **mhdr = &mymh;
  1056.     UBYTE   planepick;
  1057.  
  1058.     GUESS
  1059.     if( !mh ) {
  1060.         mhdr = NULL;
  1061.     }
  1062.     ip = chainAllocMem( mhdr, (ULONG)sizeof(struct Image),
  1063.                 MEMF_CLEAR | MEMF_PUBLIC );
  1064.     QUIF( !ip );
  1065.     ip->Width = width;
  1066.     ip->Height = height;
  1067.     ip->Depth = depth;
  1068.     if( depth > 0 && width > 0 && height > 0 ) {
  1069.         size = GIM_IMAGESIZE(depth, width, height);
  1070.         ip->ImageData = chainAllocMem( mhdr, size, MEMF_CLEAR|MEMF_CHIP );
  1071.         QUIF( !ip->ImageData );
  1072.         planepick = 1;
  1073.         while( --depth > 0 ) {
  1074.         planepick = (planepick << 1) + 1;
  1075.         } /* while */
  1076.         ip->PlanePick = planepick;
  1077.     }
  1078.     linkChainMem( mh, mymh );
  1079.     return( ip );
  1080.     ENDGUESS
  1081.     if( mhdr ) {
  1082.     chainFreeMem( mymh );
  1083.     } else {
  1084.     if( ip ) {
  1085.         FreeMem( ip, (ULONG)sizeof(struct Image) );
  1086.     }
  1087.     }
  1088.     return( NULL );
  1089. } /* gimmeImage */
  1090.  
  1091.  
  1092. struct IntuiText *gimmeIntuiText( mh, s, textattr, width )
  1093.     void    **mh;
  1094.     UBYTE   *s;
  1095.     struct TextAttr *textattr;
  1096.     SHORT   width;
  1097. {
  1098.     register struct IntuiText    *itp;
  1099.  
  1100.     GUESS
  1101.     itp = chainAllocMem( mh, (ULONG)sizeof(struct IntuiText),
  1102.                 MEMF_CLEAR | MEMF_PUBLIC );
  1103.     QUIF( !itp );
  1104.     itp->FrontPen = 1;
  1105.     itp->DrawMode = JAM2;
  1106.     itp->ITextFont = textattr;
  1107.     itp->IText = s;
  1108.     if( width > 0 ) {           /* if width given, centre text */
  1109.         itp->LeftEdge = (width - IntuiTextLength(itp)) >> 1;
  1110.     }
  1111.     return( itp );
  1112.     ENDGUESS
  1113.     return( NULL );
  1114. } /* gimmeIntuiText */
  1115. SHAR_EOF
  1116. cat << \SHAR_EOF > keyboard.c
  1117. /*
  1118.  *  FILE: keyboard.c
  1119.  *  Support routines for "cooking" raw input.
  1120.  *
  1121.  *  Public Domain, but keep my name in it as the original author.
  1122.  *  31-Aug-88    Jan Sven Trabandt   first release version
  1123.  */
  1124.  
  1125.  
  1126. #include "gimmelib/gimmefuncs.h"
  1127.  
  1128.  
  1129. SHORT deadKeyConvert( imsg, buf, bufsize, keymap )
  1130.     struct IntuiMessage *imsg;
  1131.     UBYTE        *buf;
  1132.     USHORT        bufsize;
  1133.     struct KeyMap    *keymap;
  1134. {
  1135.     struct InputEvent    ievent;
  1136.  
  1137. #ifdef GIMME_WIMPY
  1138.     if( !imsg || !buf || bufsize < 0 ) {
  1139.     return( -3 );
  1140.     }
  1141. #endif
  1142.     if( imsg->Class != RAWKEY ) {
  1143.     return( -2 );
  1144.     }
  1145.     ievent.ie_NextEvent = NULL;
  1146.     ievent.ie_Class = IECLASS_RAWKEY;
  1147.     ievent.ie_Code = imsg->Code;
  1148.     ievent.ie_Qualifier = imsg->Qualifier;
  1149.     ievent.ie_position.ie_addr = *((APTR *)imsg->IAddress);
  1150.     return( RawKeyConvert(&ievent, buf, (ULONG)bufsize, keymap) );
  1151. } /* deadKeyConvert */
  1152. SHAR_EOF
  1153. cat << \SHAR_EOF > memchain.c
  1154. /*
  1155.  *  FILE: memchain.c
  1156.  *  Support routines for chaining memory, anchored to a head which
  1157.  *  points to the latest chunk of memory allocated.
  1158.  *
  1159.  *  Public Domain, but keep my name in it as the original author.
  1160.  *  31-Aug-88    Jan Sven Trabandt   first release version
  1161.  *  31-Oct-88    Jan Sven Trabandt   chainAllocMem acts like normal AllocMem
  1162.  *                      if no memory-chain pointer given
  1163.  *                    parameters checked in all these functions
  1164.  */
  1165.  
  1166.  
  1167. #include "gimmelib/gimmefuncs.h"
  1168.  
  1169.  
  1170. struct memnode {
  1171.    struct memnode *next;
  1172.    ULONG size;
  1173. };
  1174.  
  1175.  
  1176. void *chainAllocMem( headptr, size, type )
  1177.     struct memnode  **headptr;
  1178.     ULONG   size;
  1179.     ULONG   type;
  1180. {
  1181.     register struct memnode *p;
  1182.  
  1183.     if( !headptr ) {
  1184.     p = AllocMem( size, type );
  1185.     } else {
  1186.     size += sizeof(struct memnode);
  1187.     if( p = AllocMem(size, type) ) {
  1188.         p->size = size;
  1189.         p->next = *headptr;
  1190.         *headptr = p;
  1191.         ++p;            /* make p point to user's memory */
  1192.     }
  1193.     }
  1194.     return( p );
  1195. } /* chainAllocMem */
  1196.  
  1197.  
  1198. VOID chainFreeMem( head )
  1199.     register struct memnode *head;
  1200. {
  1201.     struct memnode  *p;
  1202.  
  1203.     while( head ) {
  1204.     p = head->next;
  1205.     FreeMem( head, head->size );
  1206.     head = p;
  1207.     }
  1208. } /* chainFreeMem */
  1209.  
  1210.  
  1211. short linkChainMem( headptr, head )
  1212.     struct memnode  **headptr;
  1213.     struct memnode  *head;
  1214. {
  1215.     register struct memnode *p;
  1216.  
  1217.     if( headptr && head ) {
  1218.     p = head;
  1219.     if( *headptr ) {
  1220.         for( ; p->next; p = p->next ) {
  1221.         } /* for */
  1222.         p->next = *headptr;
  1223.     }
  1224.     *headptr = head;
  1225.     }
  1226.     return( 0 );
  1227. } /* linkChainMem */
  1228.  
  1229.  
  1230. short pluckChainMem( headptr, mem )
  1231.     struct memnode  **headptr;
  1232.     void        *mem;
  1233. {
  1234.     register struct memnode *p;
  1235.     struct memnode        *mine;
  1236.  
  1237.     if( !headptr ) {
  1238.     return( -1 );
  1239.     }
  1240.     if( mem && *headptr ) {
  1241.     mine = (struct memnode *)( ((UBYTE *) mem) -
  1242.                     (ULONG)sizeof(struct memnode) );
  1243.     if( mine == *headptr ) {
  1244.         *headptr = mine->next;
  1245.     } else {
  1246.         for( p = *headptr; p->next != mine; p = p->next ) {
  1247.         if( !p->next ) {
  1248.             return( -1 );           /* not in this chain */
  1249.         }
  1250.         } /* for */
  1251.         p->next = mine->next;
  1252.     }
  1253.     FreeMem( mine, mine->size );
  1254.     }
  1255.     return( 0 );
  1256. } /* pluckChainMem */
  1257. SHAR_EOF
  1258. cat << \SHAR_EOF > menu.c
  1259. /*
  1260.  *  FILE: menu.c
  1261.  *  Support routines for creating menu and menu item structures.
  1262.  *
  1263.  *  Public Domain, but keep my name in it as the original author.
  1264.  *  31-Oct-88    Jan Sven Trabandt   added to gimme.lib
  1265.  */
  1266.  
  1267.  
  1268. #define I_AM_MENU
  1269. #include "gimmelib/gimmefuncs.h"
  1270. #define GIM_BUILTIN
  1271. #include "gimmelib/macros.h"
  1272.  
  1273. extern struct GfxBase *GfxBase;
  1274.  
  1275. #define XLEEWAY     10        /* make menu item a little visually appealing */
  1276.  
  1277.  
  1278. struct Menu *gimmeMenu( mhptr, left, width, name, flags )
  1279.     void    **mhptr;
  1280.     SHORT   left, width;
  1281.     UBYTE   *name;
  1282.     ULONG   flags;
  1283. {
  1284.     register struct Menu    *menu;
  1285.  
  1286.     if( menu = chainAllocMem(mhptr, (ULONG)sizeof(struct Menu),
  1287.                     MEMF_PUBLIC | MEMF_CLEAR) ) {
  1288.     menu->LeftEdge = left;
  1289.     if( width >= 0 ) {
  1290.         menu->Width = width;
  1291.     } else {
  1292.         menu->Width = 9 * strlen( name );
  1293.     }
  1294.     menu->Height = 9;        /* currently ignored by Intuition */
  1295.     menu->Flags = flags;
  1296.     menu->MenuName = (BYTE *) name;
  1297.     }
  1298.     return( menu );
  1299. } /* gimmeMenu */
  1300.  
  1301.  
  1302. struct MenuItem *gimmeMenuItem( mhptr, left, width, height, command, name,
  1303.                     textattr, flags )
  1304.     void        **mhptr;
  1305.     SHORT        left;
  1306.     SHORT        width, height;
  1307.     BYTE        command;
  1308.     UBYTE        *name;
  1309.     struct TextAttr *textattr;
  1310.     ULONG        flags;
  1311. {
  1312.     register struct MenuItem    *item;
  1313.     SHORT            temp;
  1314.     void            *mymh = NULL;
  1315.  
  1316.     GUESS
  1317.     QUIF( !mhptr );
  1318.     item = chainAllocMem( &mymh, (ULONG)sizeof(struct MenuItem),
  1319.                     MEMF_PUBLIC | MEMF_CLEAR );
  1320.     QUIF( !item );
  1321.     if( flags & ITEMTEXT ) {
  1322.         item->ItemFill = (APTR) gimmeIntuiText( &mymh, name, textattr, 0 );
  1323.         QUIF( !item->ItemFill );
  1324.         ((struct IntuiText *)item->ItemFill)->DrawMode |= INVERSVID;
  1325.         if( width < 0 ) {
  1326.         width = IntuiTextLength( item->ItemFill ) + XLEEWAY;
  1327.         }
  1328.         if( height < 0 ) {
  1329.         if( textattr ) {
  1330.             height = textattr->ta_YSize;
  1331.         } else {
  1332.             height = GfxBase->DefaultFont->tf_YSize;
  1333.         }
  1334.         }
  1335.     } else {
  1336.         item->ItemFill = (APTR) name;
  1337.         if( flags & HIGHIMAGE ) {
  1338.         item->SelectFill = (APTR) textattr;
  1339.         }
  1340.         if( width < 0 ) {
  1341.         if( (struct Image *) name ) {
  1342.             width = ((struct Image *)name)->Width;
  1343.         }
  1344.         if( (struct Image *) item->SelectFill ) {
  1345.             temp = ((struct Image *)item->SelectFill)->Width;
  1346.             if( temp > width ) {
  1347.             width = temp;
  1348.             }
  1349.         }
  1350.         }
  1351.         if( height < 0 ) {
  1352.         if( (struct Image *) name ) {
  1353.             height = ((struct Image *)name)->Height;
  1354.         }
  1355.         if( (struct Image *) item->SelectFill ) {
  1356.             temp = ((struct Image *)item->SelectFill)->Height;
  1357.             if( temp > height ) {
  1358.             height = temp;
  1359.             }
  1360.         }
  1361.         }
  1362.     }
  1363.     if( flags & CHECKIT ) {
  1364.         width += CHECKWIDTH;
  1365.     }
  1366.     if( flags & COMMSEQ ) {
  1367.         width += COMMWIDTH + 4;    /* separate text/image from commseq */
  1368.     }
  1369.     item->LeftEdge = left;
  1370.     item->Width = width;
  1371.     item->Height = height;
  1372.     item->Flags = flags;
  1373.     item->Command = command;
  1374.     linkChainMem( mhptr, mymh );
  1375.     return( item );
  1376.     ENDGUESS
  1377.     if( mymh ) {
  1378.     chainFreeMem( mymh );
  1379.     }
  1380.     return( NULL );
  1381. } /* gimmeMenuItem */
  1382. SHAR_EOF
  1383. cat << \SHAR_EOF > menustuff.c
  1384. /*
  1385.  *  FILE: menustuff.c
  1386.  *  Support routines for dealing with menus and menuitems.
  1387.  *
  1388.  *  NOTE: these routines should only be used on a menustrip that is
  1389.  *  not attached to a window or guaranteed not to be actively used by
  1390.  *  Intuition (eg. by using the MENUVERIFY flag).
  1391.  *
  1392.  *  Public Domain, but keep my name in it as the original author.
  1393.  *  31-Oct-88    Jan Sven Trabandt   added to gimme.lib
  1394.  */
  1395.  
  1396.  
  1397. #define I_AM_MENUSTUFF
  1398. #include "gimmelib/gimmefuncs.h"
  1399. #include "gimmelib/menustuff.h"
  1400.  
  1401.  
  1402. /* internal flags: must stay within defined GMI_RESERVED bits */
  1403. #define GMI_SUBITEM    (1L << 30)      /* process subitem, not item */
  1404. #define GMI_DO_TOP    (1L << 29)      /* modify top edge */
  1405. #define GMI_DO_ME    (1L << 28)      /* modify mutual exclude */
  1406. #define GMI_SNEAKY    (1L << 27)      /* sneaky -- don't modify too much */
  1407.  
  1408. #define GMI_ADJUST    (GMI_FIXUP | GMI_SHUFFLE)
  1409. #define GMI_ADJUSTME    (GMI_FIXUPME | GMI_SHUFFLEME)
  1410.  
  1411.  
  1412. ULONG addMenuItem( menu, item, positem, possub, numitem, myflags )
  1413.     struct Menu     *menu;
  1414.     struct MenuItem *item;
  1415.     SHORT        positem, possub, numitem;
  1416.     ULONG        myflags;
  1417. {
  1418.     register struct MenuItem    *temp, **old;
  1419.     struct MenuItem        *save, *savelast;
  1420.     SHORT            pos, sub;
  1421.     SHORT            top, topedge;
  1422.  
  1423.     if( !menu || !item || !numitem ) {
  1424.     return( MENUNULL );
  1425.     }
  1426.     if( myflags & GMI_SUBITEM ) {
  1427.     old = &((struct MenuItem *)menu)->SubItem;
  1428.     } else {
  1429.     old = &menu->FirstItem;
  1430.     }
  1431.  
  1432.     if( myflags & GMI_ADDSUBITEM ) {
  1433.     if( !*old ) {                   /* if no items, can't put subitem */
  1434.         return( MENUNULL );
  1435.     }
  1436.     } else {
  1437.     /* find last item in list to be added and truncate list appropriately */
  1438.     for( temp = item; temp->NextItem; temp = temp->NextItem ) {
  1439.         if( --numitem == 0 ) {
  1440.         temp->NextItem = NULL;
  1441.         break;
  1442.         }
  1443.     } /* for */
  1444.     savelast = temp;        /* save pointer to last item to be added */
  1445.  
  1446.     if( positem == 0 || !*old ) {       /* add as first (sub)item */
  1447.         savelast->NextItem = *old;
  1448.         *old = item;
  1449.         if( *old && (myflags & (GMI_ADJUST|GMI_ADJUSTME|GMI_APPEAREND)) ) {
  1450.         pos = 0;
  1451.         save = item;
  1452.         myflags |= GMI_SNEAKY;        /* careful handling */
  1453.         goto calculate_adjustment_mi;
  1454.         }
  1455.         adjustMenuItems( item, savelast->NextItem, 0, 0, myflags );
  1456.         return( SHIFTITEM(0) | SHIFTSUB(NOSUB) );
  1457.     }
  1458.     }
  1459.  
  1460.     /* find the item preceding where to insert, and position# for new item */
  1461.     pos = 1;
  1462.     for( temp = *old; temp->NextItem; temp = temp->NextItem ) {
  1463.     if( --positem == 0 ) {
  1464.         break;
  1465.     }
  1466.     ++pos;
  1467.     } /* for */
  1468.  
  1469.     if( myflags & GMI_ADDSUBITEM ) {
  1470.     sub = ITEMNUM( addMenuItem(temp, item, possub, 0, numitem,
  1471.                 (myflags | GMI_SUBITEM) & ~GMI_ADDSUBITEM) );
  1472.     } else {
  1473.     savelast->NextItem = temp->NextItem;
  1474.     save = temp;            /* save ptr to item after which to add */
  1475.     if( myflags & (GMI_ADJUST | GMI_ADJUSTME) ) {
  1476. calculate_adjustment_mi: {}
  1477.         /* calculate top edge for new item */
  1478.         topedge = 0;
  1479.         for( temp = *old; temp; temp = temp->NextItem ) {
  1480.         top = temp->TopEdge + temp->Height;
  1481.         if( temp == save ) {
  1482.             if( !(myflags & GMI_SNEAKY) ) {
  1483.             save->NextItem = item;
  1484.             if( top > topedge ) {
  1485.                 topedge = top;
  1486.             }
  1487.             }
  1488.             if( !(myflags & GMI_APPEAREND) ) {
  1489.             break;            /* exit for loop */
  1490.             }
  1491.             temp = savelast;        /* skip over what we added */
  1492.         }
  1493.         if( top > topedge ) {
  1494.             topedge = top;
  1495.         }
  1496.         } /* for */
  1497.         adjustMenuItems( item, savelast->NextItem, topedge, pos, myflags );
  1498.     } else {
  1499.         save->NextItem = item;
  1500.     }
  1501.     sub = NOSUB;
  1502.     }
  1503.  
  1504.     return( SHIFTITEM(pos) | SHIFTSUB(sub) );
  1505. } /* addMenuItem */
  1506.  
  1507.  
  1508. ULONG addMenu( menuptr, menu, posmenu, nummenu, myflags )
  1509.     struct Menu     **menuptr;
  1510.     struct Menu     *menu;
  1511.     SHORT        posmenu, nummenu;
  1512.     ULONG        myflags;
  1513. {
  1514.     register struct Menu    *temp, **old;
  1515.     struct Menu         *save, *savelast;
  1516.     SHORT            pos;
  1517.     SHORT            left, leftedge;
  1518.  
  1519.     if( !nummenu || !menuptr || !menu ) {
  1520.     return( MENUNULL );
  1521.     }
  1522.     old = menuptr;
  1523.  
  1524.     /* find last menu in list to be added and truncate list appropriately */
  1525.     for( temp = menu; temp->NextMenu; temp = temp->NextMenu ) {
  1526.     if( --nummenu == 0 ) {
  1527.         temp->NextMenu = NULL;
  1528.         break;
  1529.     }
  1530.     } /* for */
  1531.     savelast = temp;        /* save pointer to last menu to be added */
  1532.  
  1533.     if( posmenu == 0 || !*old ) {       /* add to front of menu strip */
  1534.     savelast->NextMenu = *old;
  1535.     *old = menu;
  1536.     if( *old && (myflags & (GMI_ADJUST | GMI_APPEAREND)) ) {
  1537.         pos = 0;
  1538.         save = menu;
  1539.         myflags |= GMI_SNEAKY;        /* careful handling */
  1540.         goto calculate_adjustment_m;
  1541.     }
  1542.     adjustMenuLefts( menu, savelast->NextMenu, 0, myflags );
  1543.     return( SHIFTMENU(0) | SHIFTITEM(NOITEM) | SHIFTSUB(NOSUB) );
  1544.     }
  1545.  
  1546.     /* find the menu preceding where to insert, and position# for new menu */
  1547.     pos = 1;
  1548.     for( temp = *old; temp->NextMenu; temp = temp->NextMenu ) {
  1549.     if( --posmenu == 0 ) {
  1550.         break;
  1551.     }
  1552.     ++pos;
  1553.     } /* for */
  1554.  
  1555.     savelast->NextMenu = temp->NextMenu;
  1556.     save = temp;        /* save ptr to menu after which to add */
  1557.     if( myflags & (GMI_ADJUST | GMI_ADJUSTME) ) {
  1558. calculate_adjustment_m: {}
  1559.     /* calculate left edge for new menu */
  1560.     leftedge = 0;
  1561.     for( temp = *old; temp; temp = temp->NextMenu ) {
  1562.         left = temp->LeftEdge + temp->Width;
  1563.         if( temp == save ) {
  1564.         if( !(myflags & GMI_SNEAKY) ) {
  1565.             save->NextMenu = menu;
  1566.             if( left > leftedge ) {
  1567.             leftedge = left;
  1568.             }
  1569.         }
  1570.         if( !(myflags & GMI_APPEAREND) ) {
  1571.             break;            /* exit for loop */
  1572.         }
  1573.         temp = savelast;    /* skip over what we added */
  1574.         }
  1575.         if( left > leftedge ) {
  1576.         leftedge = left;
  1577.         }
  1578.     } /* for */
  1579.     adjustMenuLefts( menu, savelast->NextMenu, leftedge, myflags );
  1580.     } else {
  1581.     save->NextMenu = menu;
  1582.     }
  1583.  
  1584.     return( SHIFTMENU(pos) | SHIFTITEM(NOITEM) | SHIFTSUB(NOSUB) );
  1585. } /* addMenu */
  1586.  
  1587.  
  1588. struct MenuItem *removeMenuItem( menu, item, positem, possub, numitem, myflags )
  1589.     struct Menu     *menu;
  1590.     struct MenuItem *item;
  1591.     SHORT        positem, possub, numitem;
  1592.     ULONG        myflags;
  1593. {
  1594.     register struct MenuItem    *temp, **old;
  1595.     struct MenuItem        *save;
  1596.     SHORT            pos;        /* position for mutual exclude */
  1597.  
  1598.     if( !menu ) {
  1599.     return( NULL );
  1600.     }
  1601.     if( myflags & GMI_SUBITEM ) {
  1602.     old = &((struct MenuItem *)menu)->SubItem;
  1603.     } else {
  1604.     old = &menu->FirstItem;
  1605.     }
  1606.     if( !*old || !numitem ) {           /* if no menu items */
  1607.     return( NULL );
  1608.     }
  1609.     if( myflags & GMI_REMSUBITEM ) {
  1610.     save = item;            /* don't want to check item address yet */
  1611.     item = NULL;
  1612.     } else {
  1613.     if( item ) {
  1614.         positem = -1;
  1615.     }
  1616.     }
  1617.     pos = 0;
  1618.     temp = *old;
  1619.     if( temp != item && positem != 0 && temp->NextItem ) {
  1620.     /* find the "item" preceding where to remove */
  1621.     for( ; temp->NextItem && --positem != 0; ) {
  1622.         ++pos;
  1623.         if( temp->NextItem == item ) {      /* found the item */
  1624.         break;
  1625.         }
  1626.         temp = temp->NextItem;        /* next in loop */
  1627.         if( !temp->NextItem ) {         /* no more to follow so stop */
  1628.         break;
  1629.         }
  1630.     } /* for */
  1631.     old = &temp->NextItem;
  1632.     }
  1633.     /* now old points to a MenuItem pointer to item to be removed */
  1634.     if( item && *old != item ) {            /* if its not the right item */
  1635.     return( NULL );
  1636.     }
  1637.  
  1638.     if( myflags & GMI_REMSUBITEM ) {
  1639.     item = removeMenuItem( temp, save, possub, 0, numitem,
  1640.                 (myflags | GMI_SUBITEM) & ~GMI_REMSUBITEM );
  1641.     } else {
  1642.     if( !item ) {
  1643.         item = *old;
  1644.     }
  1645.     if( myflags & GMI_ADDRONLY ) {
  1646.         return( item );
  1647.     }
  1648.     /* find last one to be removed */
  1649.     for( temp = item; temp->NextItem; temp = temp->NextItem ) {
  1650.         if( --numitem == 0 ) {
  1651.         break;
  1652.         }
  1653.     } /* for */
  1654.     *old = temp->NextItem;
  1655.     temp->NextItem = NULL;
  1656.     myflags &= ~(GMI_FIXUP | GMI_FIXUPME);
  1657.     if( myflags & GMI_SHUFFLE ) {
  1658.         myflags |= GMI_FIXUP;
  1659.     }
  1660.     if( myflags & GMI_SHUFFLEME ) {
  1661.         myflags |= GMI_FIXUPME;
  1662.     }
  1663.     adjustMenuItems( *old, NULL, item->TopEdge, pos, myflags );
  1664.     }
  1665.  
  1666.     return( item );
  1667. } /* removeMenuItem */
  1668.  
  1669.  
  1670. struct Menu *removeMenu( menuptr, menu, posmenu, nummenu, myflags )
  1671.     struct Menu     **menuptr;
  1672.     struct Menu     *menu;
  1673.     SHORT        posmenu, nummenu;
  1674.     ULONG        myflags;
  1675. {
  1676.     register struct Menu    *temp, **old;
  1677.  
  1678.     if( !nummenu || !menuptr || !*menuptr ) {
  1679.     return( NULL );
  1680.     }
  1681.     old = menuptr;
  1682.     if( menu ) {
  1683.     posmenu = -1;
  1684.     }
  1685.     temp = *old;
  1686.     if( temp != menu && posmenu != 0 && temp->NextMenu ) {
  1687.     /* find the menu preceding where to remove */
  1688.     for( ; temp->NextMenu && --posmenu != 0; ) {
  1689.         if( temp->NextMenu == menu ) {      /* found the menu */
  1690.         break;
  1691.         }
  1692.         temp = temp->NextMenu;        /* next in loop */
  1693.         if( !temp->NextMenu ) {         /* no more to follow so stop */
  1694.         break;
  1695.         }
  1696.     } /* for */
  1697.     old = &temp->NextMenu;
  1698.     }
  1699.     /* now old points to a Menu pointer to menu to be removed */
  1700.     if( menu && *old != menu ) {            /* if its not the right menu */
  1701.     return( NULL );
  1702.     }
  1703.  
  1704.     if( !menu ) {
  1705.     menu = *old;
  1706.     }
  1707.     if( myflags & GMI_ADDRONLY ) {
  1708.     return( menu );
  1709.     }
  1710.     /* find last one to be removed */
  1711.     for( temp = menu; temp->NextMenu; temp = temp->NextMenu ) {
  1712.     if( --nummenu == 0 ) {
  1713.         break;
  1714.     }
  1715.     } /* for */
  1716.     *old = temp->NextMenu;
  1717.     temp->NextMenu = NULL;
  1718.     adjustMenuLefts( *old, NULL, menu->LeftEdge, myflags );
  1719.  
  1720.     return( menu );
  1721. } /* removeMenu */
  1722.  
  1723.  
  1724. short adjustMenuItems( item, stop, topedge, meposition, myflags )
  1725.     struct MenuItem *item, *stop;
  1726.     SHORT        topedge, meposition;
  1727.     register ULONG  myflags;
  1728. {
  1729.     register struct MenuItem    *temp;
  1730.  
  1731.     if( !(myflags & (GMI_ADJUST | GMI_ADJUSTME)) ) {
  1732.     return( -1 );
  1733.     }
  1734.     if( myflags & GMI_FIXUP ) {
  1735.     myflags |= GMI_DO_TOP;
  1736.     }
  1737.     if( myflags & GMI_FIXUPME ) {
  1738.     myflags |= GMI_DO_ME;
  1739.     }
  1740.     for( temp = item; temp; temp = temp->NextItem ) {
  1741.     if( temp == stop ) {
  1742.         if( !(myflags & (GMI_SHUFFLE | GMI_SHUFFLEME)) ) {
  1743.         break;
  1744.         }
  1745.         myflags &= ~(GMI_DO_TOP | GMI_DO_ME);
  1746.         if( (myflags & GMI_SHUFFLE) && !(myflags & GMI_APPEAREND) ) {
  1747.         myflags |= GMI_DO_TOP;
  1748.         }
  1749.         if( myflags & GMI_SHUFFLEME ) {
  1750.         myflags |= GMI_DO_ME;
  1751.         }
  1752.     }
  1753.     if( myflags & GMI_DO_TOP ) {
  1754.         temp->TopEdge = topedge;
  1755.     }
  1756.     topedge += temp->Height;
  1757.     if( myflags & GMI_DO_ME ) {
  1758.         temp->MutualExclude = ~(1L << meposition);
  1759.     }
  1760.     ++meposition;
  1761.     } /* for */
  1762.     return( 0 );
  1763. } /* adjustMenuItems */
  1764.  
  1765.  
  1766. short adjustMenuLefts( menu, stop, leftedge, myflags )
  1767.     struct Menu     *menu, *stop;
  1768.     register SHORT  leftedge;
  1769.     ULONG        myflags;
  1770. {
  1771.     register struct Menu    *temp;
  1772.  
  1773.     if( !(myflags & (GMI_ADJUST)) ) {
  1774.     return( -1 );
  1775.     }
  1776.     for( temp = menu; temp; temp = temp->NextMenu ) {
  1777.     if( !(myflags & GMI_SHUFFLE) && temp == stop ) {
  1778.         break;
  1779.     }
  1780.     temp->LeftEdge = leftedge;
  1781.     leftedge += temp->Width;
  1782.     } /* for */
  1783.     return( 0 );
  1784. } /* adjustMenuLefts */
  1785. SHAR_EOF
  1786. cat << \SHAR_EOF > message.c
  1787. /*
  1788.  *  FILE: message.c
  1789.  *  Support routines for dynamic (de)allocation of [extended] message structs
  1790.  *
  1791.  *  Public Domain, but keep my name in it as the original author.
  1792.  *  31-Aug-88    Jan Sven Trabandt   first release version
  1793.  */
  1794.  
  1795.  
  1796. #include "gimmelib/gimmefuncs.h"
  1797.  
  1798.  
  1799. struct Message *gimmeMessage( size, replyport )
  1800.     ULONG        size;
  1801.     struct MsgPort  *replyport;
  1802. {
  1803.     struct Message  *msg;
  1804.  
  1805. #ifdef GIMME_WIMPY
  1806.     if( size > 0x0FFFFL ) {
  1807.     return( NULL );
  1808.     }
  1809. #endif
  1810.     msg = (struct Message *) AllocMem( size, MEMF_PUBLIC );
  1811.     if( msg ) {
  1812.     msg->mn_Node.ln_Type = NT_FREEMSG;
  1813.     msg->mn_Node.ln_Pri = 0;
  1814.     msg->mn_Node.ln_Name = NULL;
  1815.     msg->mn_ReplyPort = replyport;
  1816.     msg->mn_Length = size;
  1817.     }
  1818.     return( msg );
  1819. } /* gimmeMessage */
  1820.  
  1821.  
  1822. short getRidOfMessage( msg )
  1823.     struct Message  *msg;
  1824. {
  1825. #ifdef GIMME_WIMPY
  1826.     if( !msg || !msg->mn_Length > 0 ) {
  1827.     return( -1 );
  1828.     }
  1829. #endif
  1830.     FreeMem( msg, (ULONG) msg->mn_Length );
  1831. } /* getRidOfMessage */
  1832. SHAR_EOF
  1833. #    End of shell archive
  1834. exit 0
  1835. -- 
  1836. Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
  1837. Have five nice days.
  1838.